package com.example.baseapp.activity

import android.content.SharedPreferences
import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentTransaction
import com.example.baseapp.R
import com.example.baseapp.activity.Fragment.TestFragment
import kotlinx.android.synthetic.main.activity_higher_order_function.*

/**
 * @作者：HuaCon
 *
 * @类描述：高阶函数
 *
 */
class HigherOrderFunctionActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_higher_order_function)
        showDome()
        applyCode()
        exampleToUse()
    }

    /**
     * 举一反三
     */
    private fun exampleToUse() {
        //sp
        getSharedPreferences("SpData", MODE_PRIVATE).open {
            putBoolean("isShown", true)
            putString("name", "huaCo")
            putInt("age", 18)
        }

        //FragmentManger
        bt_replace.setOnClickListener {
            supportFragmentManager.commit {
                replace(R.id.fl_container,TestFragment())
                addToBackStack("testFragment")
            }
        }

    }


    //1.先看demo演示效果
    private fun showDome() {
        var isPlus = false
        val num1 = 3
        val num2 = 4
        // 标准写法
        plus.setOnClickListener {
            //用::调用函数名
            tv_show.text = example(num1, num2, ::getPlus).toString()
        }
        minus.setOnClickListener {
            //用::调用函数名
            tv_show.text = example(num1, num2, ::getMinus).toString()
        }


        //推导得出lambda表达式写法
        lambda.setOnClickListener {
            if (isPlus) {
                //接受两个参数，两个参数相加操作
                tv_show.text = example(num1, num2) { n1, n2 -> n1 - n2 }.toString()
            } else {
                //接受两个参数，两个参数相减操作
                tv_show.text = example(num1, num2) { n1, n2 -> n1 + n2 }.toString()
            }
            isPlus = !isPlus
        }
    }

    //2.实际应用效果
    private fun applyCode() {
        val phones = mutableListOf("Apple", "Mi", "Oppo", "Vivo", "BBK", "Huawei")

        val builder = StringBuilder().build {
            append("开始添加手机：\n")
            for (phone in phones) {
                append("$phone\n")
            }
            append("添加结束！")
        }
        Log.d("phoneLog", "展示结果：\n$builder")
    }


    /**
     * 定义简单高阶函数
     * 定义规则：(String,Int)->Unit
     * ->左边的用来声明该函数接受什么参数，多个参数之间使用逗号隔开，
     * ->右边的用来声明该函数的返回值是什么，如果没有返回值就使用Unit
     * 此高阶函数没有什么实际的意义，函数参数接受两个整型实参，并把两个实参返回
     */
    private fun example(num1: Int, num2: Int, func: (Int, Int) -> Int): Int = func(num1, num2)

    /**
     * 定义与高阶函数相匹配的函数才能调用
     */
    private fun getPlus(num1: Int, num2: Int): Int = num1.plus(num2)
    private fun getMinus(num1: Int, num2: Int): Int = num1.minus(num2)

    /**
     * 完整的高阶函数
     * 定义规则<ClassName.>
     * 在函数类型的前面加上ClassName.就表示这个函数定义在哪个类当中
     * 为了消除调用lambda表达式带来的匿名内部类的内存开销，使用了inline内联函数
     */
    private inline fun StringBuilder.build(block: StringBuilder.() -> Unit): StringBuilder {
        block()
        return this
    }

    /**
     * Eg：SharedPreferences简化使用
     */
    private inline fun SharedPreferences.open(block: SharedPreferences.Editor.() -> Unit) {
        val editor = edit()
        editor.block()
        editor.apply()
    }

    /**
     * Eg: FragmentManager 简化使用
     */
    private inline fun FragmentManager.commit(block: FragmentTransaction.() -> Unit) {
        val transaction = beginTransaction()
        transaction.block()
        transaction.commit()
    }


}